perm filename DDSIM.SAI[S,HE] blob sn#560082 filedate 1982-04-13 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00020 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	ENTRY GDDINI,GDPYUP,GSCREN,GSCREM,GDRKEN,GLITEN,GINVEN,GDOT,GLINE,GRECTA,GELLIP,
C00006 00003	INTERNAL INTEGER PROCEDURE GGDDCH(INTEGER CHAN)
C00007 00004	INTERNAL PROCEDURE GERASE(INTEGER CHAN)
C00008 00005	INTERNAL PROCEDURE GDDINI
C00009 00006	INTERNAL PROCEDURE GDPYUP(INTEGER CHAN, DDBUFFER(-1))
C00010 00007	INTERNAL PROCEDURE GSCREN(REAL XLO,YLO,XHI,YHI)
C00011 00008	INTERNAL PROCEDURE GSCREM(REFERENCE REAL XLO,YLO,XHI,YHI)
C00012 00009	INTERNAL PROCEDURE GDRKEN
C00013 00010	INTERNAL PROCEDURE GLITEN
C00014 00011	INTERNAL PROCEDURE GINVEN
C00015 00012	INTERNAL PROCEDURE GDOT(REAL X,Y INTEGER THK(0))
C00016 00013	INTERNAL PROCEDURE GLINE(REAL X1,Y1,X2,Y2 INTEGER THK(0))
C00018 00014	INTERNAL PROCEDURE GRECTA(REAL X1,Y1,X2,Y2)
C00020 00015	INTERNAL PROCEDURE GELLIP(REAL X1,Y1,X2,Y2)
C00022 00016	INTERNAL PROCEDURE GPOLY(INTEGER N REFERENCE REAL X,Y)
C00023 00017	INTERNAL PROCEDURE GPOLYX(INTEGER N REFERENCE REAL X,Y)
C00024 00018	INTERNAL PROCEDURE GTXTPS(REAL X,Y,XS,YS,DXS(0),DYS(0))
C00025 00019	INTERNAL PROCEDURE GTEXT(STRING TXT)
C00026 00020	INTERNAL PROCEDURE GTEXTD(STRING TXT)
C00027 ENDMK
C⊗;
ENTRY GDDINI,GDPYUP,GSCREN,GSCREM,GDRKEN,GLITEN,GINVEN,GDOT,GLINE,GRECTA,GELLIP,
GPOLY,GPOLYX,GTXTPS,GTEXT,GTEXTD,GERASE,GGDDCH;

BEGIN "DDSIM"
COMMENT Simulate HPM's routines on the Grinnell.;


REQUIRE "GFNHDR.SAI[HDR,HE]"  SOURCE_FILE;
REQUIRE "GRNHDR.SAI[HDR,HE]" SOURCE_FILE;
REQUIRE "GRFHDR.SAI[HDR,HE]" SOURCE_FILE;
REQUIRE "GRNDEF[HDR,HE]" SOURCE_FILE;
INTEGER FIRSTIME;		COMMENT This must be set to zero initially.;
INTEGER WRITEMODE;		COMMENT What state the Grinnell is in. (LWM);
INTEGER IERRFG,TERRFG,SERRFG;	COMMENT Whether or not the user has committed a sin;
REAL XL,XH,YL,YH;		COMMENT The user's virtual screen.;
INTEGER XPOS, YPOS;		COMMENT Pixel position where txt will be started;

COMMENT Routines to convert from user coordinates to pixels.;
INTEGER PROCEDURE XPIX(REAL X);
RETURN((X-XL)/(XH-XL)*511 + 0.5);

INTEGER PROCEDURE YPIX(REAL Y);
RETURN((Y-YL)/(YH-YL)*479 + 0.5);  comment hardware changed...can't see top band;

COMMENT Procedures used in clipping;
DEFINE XLIMIT(VAL)="IF VAL < 0 THEN VAL←0 ELSE IF VAL > 511 THEN VAL←511";
DEFINE YLIMIT(VAL)="IF VAL < 0 THEN VAL←0 ELSE IF VAL > 479 THEN VAL←479";
DEFINE XOUT(VAL) = "((VAL<0) OR (VAL>511))";
DEFINE YOUT(VAL) = "((VAL<0) OR (VAL>479))";


COMMENT Procedure to convert letters to uppercase;
SIMPLE INTEGER PROCEDURE UPPERCASE(INTEGER I);
   RETURN(IF I>'140 ∧ I≤'172 THEN I LAND '137 ELSE I);
INTERNAL INTEGER PROCEDURE GGDDCH(INTEGER CHAN);
BEGIN "GGDDCH"
COMMENT Don't really get a DD channel, just return the Grinnell one.;
	RETURN('43)
END "GGDDCH";
INTERNAL PROCEDURE GERASE(INTEGER CHAN);
BEGIN "GERASE"
COMMENT If they try to "erase" the Grinnell channel, use an ERS.;
	IF CHAN = '43 THEN GRNINS(ERS)
END "GERASE";
INTERNAL PROCEDURE GDDINI;
BEGIN "GDDINI"
COMMENT Set up the Grinnell in single-user mode.;
	COMMENT This little hack allows multiple calls to DDINIT but it assumes
		that FIRSTIME is set to zero by the loader.;
	IF FIRSTIME=0 THEN
	    BEGIN
		GRNINI;
		FIRSTIME ← 1
	    END;
	GRNINS(LDC LOR 1);
	GRNINS(LSM LOR '377);	COMMENT All eight bits;
	comment Put code here to set up intensity map.;
	IERRFG ← TRUE;
	TERRFG ← TRUE;
	SERRFG ← TRUE;
	WRITEMODE ← 0;
	GRNINS(LWM LOR WRITEMODE);
	COMMENT Erase the screen;
	GRNINS(ERS);
END "GDDINI";

INTERNAL PROCEDURE GDPYUP(INTEGER CHAN, DDBUFFER(-1));
BEGIN "GDPYUP"
BUFOUT
END "GDPYUP";
INTERNAL PROCEDURE GSCREN(REAL XLO,YLO,XHI,YHI);
BEGIN "GSCREN"
COMMENT Set up screen parameters.;
XL ← XLO;
YL ← YLO;
XH ← XHI;
YH ← YHI
END "GSCREN";

INTERNAL PROCEDURE GSCREM(REFERENCE REAL XLO,YLO,XHI,YHI);
BEGIN "GSCREM"
COMMENT Return screen parameters.;
XLO ← XL;
YLO ← YL;
XHI ← XH;
YHI ← YH
END "GSCREM";

INTERNAL PROCEDURE GDRKEN;
BEGIN "GDRKEN"
COMMENT Set up inverted background write mode.;
WRITEMODE ← WRITEMODE LOR BITB;
GRNINS(LWM LOR WRITEMODE)
END "GDRKEN";

INTERNAL PROCEDURE GLITEN;
BEGIN "GLITEN"
COMMENT Set up non-inverted background write mode.;
WRITEMODE ← WRITEMODE LAND (LNOT BITB);
GRNINS(LWM LOR WRITEMODE)
END "GLITEN";

INTERNAL PROCEDURE GINVEN;
BEGIN "GINVEN"
COMMENT There's no hardware to do this...just cop out.;
IF IERRFG THEN
    BEGIN
	PRINT("WARNING...INVEN doesn't work properly."&'15&'12);
	IERRFG ← FALSE
    END;
GDRKEN
END "GINVEN";

INTERNAL PROCEDURE GDOT(REAL X,Y; INTEGER THK(0));
BEGIN "GDOT"
COMMENT Do a dot;
INTEGER XP,YP;			COMMENT Pixel position of dot;
IF TERRFG AND (THK≠0) THEN
    BEGIN
	PRINT("WARNING...Thickness on graphics doesn't work properly."&'15&'12);
	TERRFG ← FALSE
    END;
COMMENT Don't plot an out-of-range dot.;
YP ← YPIX(Y); XP ← XPIX(X);
IF (XP≥0) AND (XP≤511) AND (YP≥0) AND (XP≤511) THEN GRNDOT(XP,YP,'377)
END "GDOT";

INTERNAL PROCEDURE GLINE(REAL X1,Y1,X2,Y2; INTEGER THK(0));
BEGIN "GLINE"
COMMENT Draw a line on the Grinnell.;
SIMPLE PROCEDURE DRAWIT(REFERENCE REAL X1,Y1,X2,Y2);
  BEGIN INTEGER IX1,IY1,IX2,IY2;
	IX1 ← X1*511 + 0.5; IX2 ← X2*511 + 0.5;
	IY1 ← Y1*479 + 0.5; IY2 ← Y2*479 + 0.5; comment hardware change...;
	GRNLINE(IX1,IY1,IX2,IY2,'377)
  END;

IF TERRFG AND (THK≠0) THEN
    BEGIN
	PRINT("WARNING...Thickness on graphics doesn't work properly."&'15&'12);
	TERRFG ← FALSE
    END;

COMMENT Find normalized device coordinates.;
X1 ← (X1-XL)/(XH-XL); X2 ← (X2-XL)/(XH-XL);
Y1 ← (Y1-YL)/(YH-YL); Y2 ← (Y2-YL)/(YH-YL);

COMMENT If vector mode is not set, set it.;
IF (WRITEMODE LAND BITV) = 0 THEN
    BEGIN
	WRITEMODE ← WRITEMODE LOR BITV;
	GRNINS(LWM LOR WRITEMODE)
    END;

COMMENT Then clip and draw the line.;
CLIP2DNORM(DRAWIT,X1,Y1,X2,Y2)
END "GLINE";

INTERNAL PROCEDURE GRECTA(REAL X1,Y1,X2,Y2);
BEGIN "GRECTA"
COMMENT Draw a rectangle bounded by the two corners.;
INTEGER XP1,YP1,XP2,YP2;

XP1 ← XPIX(X1); XP2 ← XPIX(X2);
YP1 ← YPIX(Y1); YP2 ← YPIX(Y2);

COMMENT Clip to screen boundaries.;
COMMENT This code doesn't work if the screen is in the middle of the rectangle,
	someone should fix it some day;
IF (XOUT(XP1) AND XOUT(XP2)) OR (YOUT(YP1) AND YOUT(YP2)) THEN RETURN;
XLIMIT(XP1); XLIMIT(XP2); YLIMIT(YP1); YLIMIT(YP2);

COMMENT Set up Ea, Eb to small x, size;
IF XP2 > XP1 THEN
    BEGIN
	GRNINS(LEA LOR XP1); GRNINS(LEB LOR (XP2-XP1))
    END
ELSE
    BEGIN
	GRNINS(LEA LOR XP2); GRNINS(LEB LOR (XP1-XP2))
    END;

COMMENT And La, Lb to small y, size;
IF YP2 > YP1 THEN
    BEGIN
	GRNINS(LLA LOR YP1); GRNINS(LLB LOR (YP2-YP1))
    END
ELSE
    BEGIN
	GRNINS(LLA LOR XP1); GRNINS(LLB LOR (YP1-YP2))
    END;

COMMENT If rectilinear mode is not set, set it.;
IF (WRITEMODE LAND BITV) ≠ 0 THEN
    BEGIN
	WRITEMODE ← WRITEMODE LAND (LNOT BITV);
	GRNINS(LWM LOR WRITEMODE)
    END;

COMMENT And now actually draw the rectangle.;
GRNINS(EGW)
END "GRECTA";

INTERNAL PROCEDURE GELLIP(REAL X1,Y1,X2,Y2);
BEGIN "GELLIP"
COMMENT Draw the ellipse which is surrounded by the given box.;

INTEGER L,R;			COMMENT Pixel coords. of one line.;
INTEGER YLINE;			COMMENT Used to clip ellipse to screen.;
INTEGER XC,YC;			COMMENT Pixel coords. of center of ellipse.;
INTEGER X,Y;			COMMENT Pixel values of offsets from center.;
INTEGER A,B;			COMMENT Ellipse half-height and half-width:
					these appear in the equation
					(x/a)↑2 + (y/b)↑2 = 1;

COMMENT If vector mode is not set, set it.;
IF (WRITEMODE LAND BITV) = 0 THEN
    BEGIN
	WRITEMODE ← WRITEMODE LOR BITV;
	GRNINS(LWM LOR WRITEMODE)
    END;

XC ← XPIX((X1+X2)/2); YC ← YPIX((Y1+Y2)/2);
A ← XC - XPIX(X1); B ← YC - YPIX(Y1);

FOR Y ← 0 STEP (IF B>0 THEN 1 ELSE -1) UNTIL B DO
    BEGIN
	COMMENT Solve ellipse equation for x.;
	X ← SQRT(A*A*(1-Y*Y/(B*B)));
	L ← XC-X; R ← XC+X;
	IF NOT(XOUT(L) AND XOUT(R)) THEN
	    BEGIN
		XLIMIT(L);
		XLIMIT(R);
		FOR YLINE ← YC+Y,YC-Y DO
		    IF NOT YOUT(YLINE) THEN
			GRNLINE(L,YLINE,R,YLINE,'377)
	    END
    END

END "GELLIP";
INTERNAL PROCEDURE GPOLY(INTEGER N; REFERENCE REAL X,Y);
  BEGIN "GPOLY"
    INTEGER i, XLOC, YLOC;
    INTEGER ARRAY PTS[1:N,1:2];

    XLOC ← LOCATION(X);
    YLOC ← LOCATION(Y);

    FOR i ← 1 STEP 1 UNTIL N DO BEGIN
	PTS[i,1] ← XPIX(MEMORY[XLOC + I - 1,REAL]);
	PTS[i,2] ← YPIX(MEMORY[YLOC + I - 1,REAL]);
    END;
    GRNPOLY(PTS,N);
  END "GPOLY";
INTERNAL PROCEDURE GPOLYX(INTEGER N; REFERENCE REAL X,Y);
  BEGIN GPOLY(N,X,Y); END;
INTERNAL PROCEDURE GTXTPS(REAL X,Y,XS,YS,DXS(0),DYS(0));
  BEGIN "GTXTPS"
    XPOS ← XPIX(X);
    YPOS ← YPIX(Y);
    IF SERRFG AND (DXS ≠ 0 AND DYS ≠ 0 AND XS ≠ 1 AND YS ≠ 0) THEN BEGIN
	SERRFG ← FALSE;
	PRINT("WARNING...Italics and slant on graphics do not work properly."
		&'15&'12);
    END;
  END "GTXTPS";
INTERNAL PROCEDURE GTEXT(STRING TXT);
  BEGIN "GTEXT"
      INTEGER ARRAY asciiTXT[1:LENGTH(TXT)];
      INTEGER len, I;
      len ← length(TXT);
      FOR I ← 1 STEP 1 UNTIL LEN DO ASCIITXT[I] ← UPPERCASE(TXT[I FOR 1]);
      Comment the Grinnell only has upper case at the momment;
      GRNTXTD(Xpos, ypos, asciiTXT, len);
  END "GTEXT";
INTERNAL PROCEDURE GTEXTD(STRING TXT);
  BEGIN GTEXT(TXT); END;

END "DDSIM"